package com.lncg.service.impl;

import com.lncg.entity.BusinessPortConfig;
import com.lncg.service.IBusinessPortConfigService;
import com.lncg.service.IDynamicPortService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 动态端口管理服务实现类
 * 
 * 实现端口的动态检测、启动和停止功能。
 * 维护当前运行的端口状态，支持动态调整。
 * 
 * @author LNCG
 * @version 1.2.0
 * @since 2024-10-17
 */
@Service
public class DynamicPortServiceImpl implements IDynamicPortService {
    
    /** 日志记录器 */
    private static final Logger logger = LoggerFactory.getLogger(DynamicPortServiceImpl.class);
    
    /** 业务端口配置服务 */
    @Autowired
    private IBusinessPortConfigService businessPortConfigService;
    
    /** 设备数据处理处理器 */
    @Autowired
    private com.lncg.handler.DeviceDataHandler deviceDataHandler;
    
    // ==================== 配置参数 ====================
    
    /** 读空闲超时时间（秒） */
    @Value("${netty.server.idle.reader-idle:30}")
    private int readerIdleTime;
    
    /** 写空闲超时时间（秒） */
    @Value("${netty.server.idle.writer-idle:60}")
    private int writerIdleTime;
    
    /** 读写空闲超时时间（秒） */
    @Value("${netty.server.idle.all-idle:90}")
    private int allIdleTime;
    
    /** Boss线程数 */
    @Value("${netty.server.boss-threads:1}")
    private int bossThreads;
    
    /** Worker线程数 */
    @Value("${netty.server.worker-threads:16}")
    private int workerThreads;
    
    // ==================== 运行时状态 ====================
    
    /** 当前运行的端口通道映射 port -> Channel */
    private final Map<Integer, Channel> runningChannels = new ConcurrentHashMap<>();
    
    /** Netty线程组 */
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    
    /** ServerBootstrap实例 */
    private ServerBootstrap bootstrap;
    
    /**
     * 初始化Netty组件
     */
    private void initializeNetty() {
        if (bootstrap == null) {
            bossGroup = new NioEventLoopGroup(bossThreads);
            workerGroup = new NioEventLoopGroup(workerThreads);
            
            bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .option(ChannelOption.SO_REUSEADDR, true)
                    // 添加连接超时配置
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    // 添加接收缓冲区大小限制
                    .childOption(ChannelOption.SO_RCVBUF, 1024 * 1024)
                    .childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 确保空闲检测器正确配置
                            pipeline.addLast(new IdleStateHandler(readerIdleTime, writerIdleTime, allIdleTime, TimeUnit.SECONDS));
                            pipeline.addLast(deviceDataHandler);
                        }
                    });
            
            logger.info("Netty组件初始化完成 - 读空闲:{}s, 写空闲:{}s, 全空闲:{}s", 
                readerIdleTime, writerIdleTime, allIdleTime);
        }
    }
    
    @Override
    public PortChangeResult detectPortChanges() {
        try {
            // 获取数据库中的启用端口配置
            List<BusinessPortConfig> enabledConfigs = businessPortConfigService.getAllEnabledConfigs();
            List<Integer> enabledPorts = enabledConfigs.stream()
                    .map(cfg -> {
                        try {
                            return cfg.getPort();
                        } catch (Exception e) {
                            return -1; // 非法端口占位，后续不会匹配
                        }
                    })
                    .filter(p -> p != -1)
                    .collect(Collectors.toList());
            
            // 获取当前运行的端口
            List<Integer> runningPorts = new ArrayList<>(runningChannels.keySet());
            
            // 找出需要启动的端口（数据库中有但未运行的）
            List<BusinessPortConfig> portsToStart = enabledConfigs.stream()
                    .filter(config -> {
                        try {
                            int p = config.getPort();
                            return !runningPorts.contains(p);
                        } catch (Exception e) {
                            return false;
                        }
                    })
                    .collect(Collectors.toList());
            
            // 找出需要停止的端口（正在运行但数据库中没有的）
            List<Integer> portsToStop = runningPorts.stream()
                    .filter(port -> !enabledPorts.contains(port))
                    .collect(Collectors.toList());
            
            logger.debug("端口变化检测 - 需要启动: {}, 需要停止: {}", 
                portsToStart.size(), portsToStop.size());
            
            return new PortChangeResult(portsToStart, portsToStop);
        } catch (Exception e) {
            logger.error("检测端口变化失败: {}", e.getMessage(), e);
            return new PortChangeResult(new ArrayList<BusinessPortConfig>(), new ArrayList<Integer>());
        }
    }
    
    @Override
    public boolean startPort(Integer port) {
        try {
            // 确保Netty组件已初始化
            initializeNetty();
            
            // 检查端口是否已经在运行
            if (runningChannels.containsKey(port)) {
                logger.warn("端口 {} 已经在运行中", port);
                return true;
            }
            
            // 绑定端口并启动监听
            ChannelFuture future = bootstrap.bind(port).sync();
            Channel channel = future.channel();
            runningChannels.put(port, channel);
            
            // 更新数据库状态
            businessPortConfigService.updateRunningStatus(port, 1);
            
            logger.info("端口 {} 启动成功", port);
            return true;
        } catch (Exception e) {
            logger.error("启动端口 {} 失败: {}", port, e.getMessage(), e);
            // 确保数据库状态为停止
            businessPortConfigService.updateRunningStatus(port, 0);
            return false;
        }
    }
    
    @Override
    public boolean stopPort(Integer port) {
        return stopPort(port, true);
    }
    
    /**
     * 停止指定端口
     * 
     * @param port 要停止的端口号
     * @param updateDatabase 是否更新数据库状态
     * @return true 停止成功，false 停止失败
     */
    public boolean stopPort(Integer port, boolean updateDatabase) {
        try {
            Channel channel = runningChannels.get(port);
            if (channel == null) {
                logger.warn("端口 {} 未在运行中", port);
                return true;
            }
            
            // 关闭通道
            channel.close().sync();
            runningChannels.remove(port);
            
            // 根据参数决定是否更新数据库状态
            if (updateDatabase) {
                businessPortConfigService.updateRunningStatus(port, 0);
                logger.info("端口 {} 停止成功，已更新数据库状态", port);
            } else {
                logger.info("端口 {} 停止成功，保持数据库状态不变", port);
            }
            
            return true;
        } catch (Exception e) {
            logger.error("停止端口 {} 失败: {}", port, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public List<Integer> getRunningPorts() {
        return new ArrayList<>(runningChannels.keySet());
    }
    
    /**
     * 停止所有端口（程序关闭时使用，不更新数据库状态）
     */
    public void stopAllPorts() {
        stopAllPorts(false);
    }
    
    /**
     * 停止所有端口
     * 
     * @param updateDatabase 是否更新数据库状态
     */
    public void stopAllPorts(boolean updateDatabase) {
        try {
            for (Integer port : new ArrayList<>(runningChannels.keySet())) {
                stopPort(port, updateDatabase);
            }
            String statusMsg = updateDatabase ? "已更新数据库状态" : "保持数据库状态不变";
            logger.info("所有端口已停止，{}", statusMsg);
        } catch (Exception e) {
            logger.error("停止所有端口失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 关闭Netty组件
     */
    public void shutdown() {
        try {
            stopAllPorts();
            
            if (workerGroup != null) {
                workerGroup.shutdownGracefully().sync();
            }
            if (bossGroup != null) {
                bossGroup.shutdownGracefully().sync();
            }
            
            logger.info("Netty组件已关闭");
        } catch (Exception e) {
            logger.error("关闭Netty组件失败: {}", e.getMessage(), e);
        }
    }
}
